/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package me.panpf.sketch.sample.widget;

import me.panpf.sketch.Configuration;
import me.panpf.sketch.Sketch;
import me.panpf.sketch.SketchImageView;
import me.panpf.sketch.datasource.DataSource;
import me.panpf.sketch.decode.ImageOrientationCorrector;
import me.panpf.sketch.drawable.SketchDrawable;
import me.panpf.sketch.sample.ResourceTable;
import me.panpf.sketch.sample.util.ApplyWallpaperAsyncTask;
import me.panpf.sketch.sample.util.FileUtils;
import me.panpf.sketch.sample.util.SaveImageAsyncTask;
import me.panpf.sketch.uri.FileUriModel;
import me.panpf.sketch.uri.GetDataSourceException;
import me.panpf.sketch.uri.UriModel;
import me.panpf.sketch.uri.UriModelManager;
import me.panpf.sketch.util.ExifInterface;
import me.panpf.sketch.util.SketchUtils;
import me.panpf.sketch.util.TextUtils;
import me.panpf.sketch.util.Utils;
import me.panpf.sketch.zoom.BlockDisplayer;
import me.panpf.sketch.zoom.ImageZoomer;
import ohos.aafwk.ability.Ability;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.TextAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.app.Context;
import ohos.media.image.ImageSource;
import ohos.media.image.common.ImageInfo;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Locale;

import static ohos.agp.components.Image.ScaleMode.*;

/**
 * DialogHolder
 */
public class DialogHolder {

    private static DialogHolder INSTANCE = new DialogHolder();
    private CommonDialog infoDialog;
    private CommonDialog zoomDialog;
    private CommonDialog scaleTypeDialog;
    private Runnable autoPlayRunnable;

    private DialogHolder() {
    }

    public static DialogHolder getInstance() {
        return INSTANCE;
    }

    /**
     * setAutoPlayCallback
     * @param runnable
     */
    public void setAutoPlayCallback(Runnable runnable) {
        this.autoPlayRunnable = runnable;
    }

    /**
     * showInfoDialog
     * @param image
     */
    public void showInfoDialog(SketchImageView image) {
        if (infoDialog == null || !infoDialog.isShowing()) {
            infoDialog = new CommonDialog(image.getContext());
            infoDialog.setAutoClosable(true);
            infoDialog.setCornerRadius(0);
            ComponentContainer root = (ComponentContainer) LayoutScatter.getInstance(image.getContext())
                    .parse(ResourceTable.Layout_dialog_detailinfo_content, null, false);
            infoDialog.setContentCustomComponent(root);
            infoDialog.setSize(1000, 900);
            Text text1 = (Text) root.findComponentById(ResourceTable.Id_text1);
            Text text2 = (Text) root.findComponentById(ResourceTable.Id_text2);
            text2.setTextColor(Color.GRAY);
            Text text3 = (Text) root.findComponentById(ResourceTable.Id_text3);
            text3.setTextColor(Color.GRAY);
            Text text4 = (Text) root.findComponentById(ResourceTable.Id_text4);
            Text text5 = (Text) root.findComponentById(ResourceTable.Id_text5);
            Text text6 = (Text) root.findComponentById(ResourceTable.Id_text6);
            text6.setTextColor(Color.GRAY);
            Text text7 = (Text) root.findComponentById(ResourceTable.Id_text7);

            text1.setClickedListener(component1 -> {
                infoDialog.destroy();
                showInfoItemDialog(image, image.getContext());
            });
            text2.setClickable(false);

            text3.setClickable(false);
            text4.setClickedListener(component12 -> {
                infoDialog.destroy();
                if (autoPlayRunnable != null) {
                    autoPlayRunnable.run();
                }
            });
            text5.setClickedListener(component13 -> {
                infoDialog.destroy();
                setWallpaper(image, (Ability) image.getContext());
            });
            text6.setClickable(false);
            text7.setClickedListener(component13 -> {
                infoDialog.destroy();
                save(image, (Ability) image.getContext());
            });
            infoDialog.show();
        }
    }

    private String assembleImageInfo(Context context, String key, String uri, long byteCount, Size size,
            Size originSize, String mimeType, int exifOrientation, PixelFormat format) {
        StringBuilder messageBuilder = new StringBuilder();
        messageBuilder.append(key);

        UriModel uriModel = UriModel.match(context, uri);
        DataSource dataSource = null;
        if (uriModel != null) {
            try {
                dataSource = uriModel.getDataSource(context, uri, null);
            } catch (GetDataSourceException e) {
                e.printStackTrace();
            }
        }

        long imageLength = 0;
        try {
            imageLength = (dataSource != null) ? dataSource.getLength() : 0;
        } catch (IOException e) {
            e.printStackTrace();
        }

        String needDiskSpace = (imageLength > 0) ? FileUtils.formetFileSize(imageLength) : "Unknown";

        long pixelByteCount = byteCount / size.width / size.height;

        long originImageByteCount = originSize.width * originSize.height * pixelByteCount;
        String needMemory = FileUtils.formetFileSize(originImageByteCount);
        String huanHang = context.getString(ResourceTable.String_huanhang);
        messageBuilder.append(huanHang);
        messageBuilder.append(huanHang);
        messageBuilder.append("Original: ")
                .append(originSize.width).append("x").append(originSize.height)
                .append("/").append((mimeType != null && mimeType.startsWith("image/")) ? mimeType.substring(6) : "Unknown")
                .append("/").append(needDiskSpace);
        messageBuilder.append(huanHang);
        messageBuilder.append("                ");
        messageBuilder.append(ImageOrientationCorrector.toName(exifOrientation))
                .append("/").append(needMemory);

        messageBuilder.append(huanHang);
        messageBuilder.append(huanHang);
        messageBuilder.append("Preview: ")
                .append(size.width).append("x").append(size.height)
                .append("/").append(format)
                .append("/").append(FileUtils.formetFileSize(byteCount));

        return messageBuilder.toString();
    }

    private String assembleImageInfo(Context context, Element drawable, SketchDrawable sketchDrawable) {
        return assembleImageInfo(context, sketchDrawable.getKey(), sketchDrawable.getUri(), sketchDrawable.getByteCount(),
                new Size(drawable.getWidth(), drawable.getHeight()),
                new Size(sketchDrawable.getOriginWidth(), sketchDrawable.getOriginHeight()),
                sketchDrawable.getMimeType(), sketchDrawable.getExifOrientation(), sketchDrawable.getBitmapConfig()
        );
    }

    private void showInfoItemDialog(SketchImageView view, Context ability) {
        CommonDialog dialog = new CommonDialog(ability);
        Element drawable = view.getDrawable();
        Component component = LayoutScatter.getInstance(ability).parse(ResourceTable.Layout_dialog_button, null, false);
        dialog.setContentCustomComponent(component);
        dialog.setAutoClosable(true);
        Text text = (Text) component.findComponentById(ResourceTable.Id_title);
        text.setMultipleLine(true);
        Button button = (Button) component.findComponentById(ResourceTable.Id_button);
        if (drawable instanceof SketchDrawable) {
            text.setText(assembleImageInfo(view.getContext(), drawable, ((SketchDrawable) drawable)));
        } else {
            String uri = view.getUri();
            UriModel uriModel = UriModel.match(Sketch.with(view.getContext()), uri);
            String optionsKey = view.getOptionsKey();
            String key = SketchUtils.makeRequestKey(uri, uriModel, optionsKey);

            ImageSource imageSource = view.getImageSource();
            long byteCount = SketchUtils.getByteCount(imageSource);
            Size size = new Size(drawable.getWidth(), drawable.getHeight());
            ImageInfo imageInfo = imageSource.getImageInfo();
            Size originSize = new Size(imageInfo.size.width, imageInfo.size.height);

            int exifOrientation = ExifInterface.ORIENTATION_UNDEFINED;
            try {
                Configuration configuration = Sketch.with(view.getContext()).getConfiguration();
                ImageOrientationCorrector imageOrientationCorrector = configuration.getOrientationCorrector();
                UriModelManager manager = Sketch.with(view.getContext()).getConfiguration().getUriModelManager();
                DataSource dataSource = manager.match(uri).getDataSource(view.getContext(), uri, null);
                exifOrientation = imageOrientationCorrector.readExifOrientation(imageSource.getSourceInfo().encodedFormat,
                        dataSource);
            } catch (GetDataSourceException ignored) {
                ignored.printStackTrace();
            }

            String str = assembleImageInfo(view.getContext(), key, uri, byteCount, size, originSize, "image/gif",
                    exifOrientation, imageInfo.pixelFormat);
            text.setText(str);
        }
        dialog.setSize(AttrHelper.vp2px(320, ability), AttrHelper.vp2px(250, ability));

        button.setText("CANCEL");
        button.setClickedListener(component1 -> dialog.destroy());

        dialog.show();
    }

    /**
     * setWallpaper
     * @param view
     * @param ability
     */
    public void setWallpaper(SketchImageView view, Context ability) {
        if (ability == null) {
            return;
        }

        Element drawable = view.getDrawable();
        String imageUri = (drawable instanceof SketchDrawable) ? ((SketchDrawable) drawable).getUri() :
                null;
        if (TextUtils.isEmpty(imageUri)) {
            Utils.toast(ability, "The Image is not ready yet");
            return;
        }

        File imageFile = getImageFile(imageUri, ability);
        if (imageFile == null) {
            Utils.toast(ability, "The Image is not ready yet");
            return;
        }
        new ApplyWallpaperAsyncTask(ability, imageFile).execute();
    }

    /**
     * getImageFile
     * @param imageUri
     * @param ability
     * @return File
     */
    public File getImageFile(String imageUri, Context ability) {
        if (ability == null) {
            return null;
        }
        if (TextUtils.isEmpty(imageUri)) {
            return null;
        }

        UriModel uriModel = UriModel.match(ability, imageUri);
        if (uriModel == null) {
            Utils.toast(ability, "Unknown format uri:" + imageUri);
            return null;
        }

        DataSource dataSource;
        try {
            dataSource = uriModel.getDataSource(ability, imageUri, null);
        } catch (GetDataSourceException e) {
            e.printStackTrace();
            Utils.toast(ability, "The Image is not ready yet");
            return null;
        }

        try {
            return dataSource.getFile(ability.getExternalCacheDir(), "wallpager.png");
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * share
     * @param view
     * @param ability
     */
    public void share(SketchImageView view, Ability ability) {
        if (ability == null) {
            return;
        }

        String imageUri = view.getUri();

        if (TextUtils.isEmpty(imageUri)) {
            Utils.toast(ability, "Please wait later");
            return;
        }

        File imageFile = getImageFile(imageUri, ability);
        if (imageFile == null) {
            Utils.toast(ability, "The Image is not ready yet");
            return;
        }
    }

    /**
     * save
     * @param view
     * @param ability
     */
    public void save(SketchImageView view, Ability ability) {
        if (ability == null) {
            return;
        }

        String imageUri = view.getUri();

        if (TextUtils.isEmpty(imageUri)) {
            Utils.toast(ability, "Please wait later");
            return;
        }

        UriModel uriModel = UriModel.match(ability, imageUri);
        if (uriModel == null) {
            Utils.toast(ability, "Unknown format uri: " + imageUri);
            return;
        }

        if (uriModel instanceof FileUriModel) {
            Utils.toast(ability, "This image is the local no need to save");
            return;
        }

        DataSource dataSource;
        try {
            dataSource = uriModel.getDataSource(ability, imageUri, null);
        } catch (GetDataSourceException e) {
            e.printStackTrace();
            Utils.toast(ability, "The Image is not ready yet");
            return;
        }

        new SaveImageAsyncTask(ability, dataSource, imageUri).execute("");
    }
}
